home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / lib / python2.5 / CGIHTTPServer.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-29  |  10KB  |  385 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. """CGI-savvy HTTP Server.
  5.  
  6. This module builds on SimpleHTTPServer by implementing GET and POST
  7. requests to cgi-bin scripts.
  8.  
  9. If the os.fork() function is not present (e.g. on Windows),
  10. os.popen2() is used as a fallback, with slightly altered semantics; if
  11. that function is not present either (e.g. on Macintosh), only Python
  12. scripts are supported, and they are executed by the current process.
  13.  
  14. In all cases, the implementation is intentionally naive -- all
  15. requests are executed sychronously.
  16.  
  17. SECURITY WARNING: DON'T USE THIS CODE UNLESS YOU ARE INSIDE A FIREWALL
  18. -- it may execute arbitrary Python code or external programs.
  19.  
  20. Note that status code 200 is sent prior to execution of a CGI script, so
  21. scripts cannot send other status codes such as 302 (redirect).
  22. """
  23. __version__ = '0.4'
  24. __all__ = [
  25.     'CGIHTTPRequestHandler']
  26. import os
  27. import sys
  28. import urllib
  29. import BaseHTTPServer
  30. import SimpleHTTPServer
  31. import select
  32.  
  33. class CGIHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
  34.     '''Complete HTTP server with GET, HEAD and POST commands.
  35.  
  36.     GET and HEAD also support running CGI scripts.
  37.  
  38.     The POST command is *only* implemented for CGI scripts.
  39.  
  40.     '''
  41.     have_fork = hasattr(os, 'fork')
  42.     have_popen2 = hasattr(os, 'popen2')
  43.     have_popen3 = hasattr(os, 'popen3')
  44.     rbufsize = 0
  45.     
  46.     def do_POST(self):
  47.         '''Serve a POST request.
  48.  
  49.         This is only implemented for CGI scripts.
  50.  
  51.         '''
  52.         if self.is_cgi():
  53.             self.run_cgi()
  54.         else:
  55.             self.send_error(501, 'Can only POST to CGI scripts')
  56.  
  57.     
  58.     def send_head(self):
  59.         '''Version of send_head that support CGI scripts'''
  60.         if self.is_cgi():
  61.             return self.run_cgi()
  62.         else:
  63.             return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self)
  64.  
  65.     
  66.     def is_cgi(self):
  67.         """Test whether self.path corresponds to a CGI script.
  68.  
  69.         Return a tuple (dir, rest) if self.path requires running a
  70.         CGI script, None if not.  Note that rest begins with a
  71.         slash if it is not empty.
  72.  
  73.         The default implementation tests whether the path
  74.         begins with one of the strings in the list
  75.         self.cgi_directories (and the next character is a '/'
  76.         or the end of the string).
  77.  
  78.         """
  79.         path = self.path
  80.         for x in self.cgi_directories:
  81.             i = len(x)
  82.             if path[:i] == x:
  83.                 if not path[i:] or path[i] == '/':
  84.                     self.cgi_info = (path[:i], path[i + 1:])
  85.                     return True
  86.                     continue
  87.         
  88.         return False
  89.  
  90.     cgi_directories = [
  91.         '/cgi-bin',
  92.         '/htbin']
  93.     
  94.     def is_executable(self, path):
  95.         '''Test whether argument path is an executable file.'''
  96.         return executable(path)
  97.  
  98.     
  99.     def is_python(self, path):
  100.         '''Test whether argument path is a Python script.'''
  101.         (head, tail) = os.path.splitext(path)
  102.         return tail.lower() in ('.py', '.pyw')
  103.  
  104.     
  105.     def run_cgi(self):
  106.         '''Execute a CGI script.'''
  107.         path = self.path
  108.         (dir, rest) = self.cgi_info
  109.         i = path.find('/', len(dir) + 1)
  110.         while i >= 0:
  111.             nextdir = path[:i]
  112.             nextrest = path[i + 1:]
  113.             scriptdir = self.translate_path(nextdir)
  114.             if os.path.isdir(scriptdir):
  115.                 dir = nextdir
  116.                 rest = nextrest
  117.                 i = path.find('/', len(dir) + 1)
  118.                 continue
  119.             break
  120.         i = rest.rfind('?')
  121.         if i >= 0:
  122.             rest = rest[:i]
  123.             query = rest[i + 1:]
  124.         else:
  125.             query = ''
  126.         i = rest.find('/')
  127.         if i >= 0:
  128.             script = rest[:i]
  129.             rest = rest[i:]
  130.         else:
  131.             script = rest
  132.             rest = ''
  133.         scriptname = dir + '/' + script
  134.         scriptfile = self.translate_path(scriptname)
  135.         if not os.path.exists(scriptfile):
  136.             self.send_error(404, 'No such CGI script (%r)' % scriptname)
  137.             return None
  138.         
  139.         if not os.path.isfile(scriptfile):
  140.             self.send_error(403, 'CGI script is not a plain file (%r)' % scriptname)
  141.             return None
  142.         
  143.         ispy = self.is_python(scriptname)
  144.         if not ispy:
  145.             if not self.have_fork and self.have_popen2 or self.have_popen3:
  146.                 self.send_error(403, 'CGI script is not a Python script (%r)' % scriptname)
  147.                 return None
  148.             
  149.             if not self.is_executable(scriptfile):
  150.                 self.send_error(403, 'CGI script is not executable (%r)' % scriptname)
  151.                 return None
  152.             
  153.         
  154.         env = { }
  155.         env['SERVER_SOFTWARE'] = self.version_string()
  156.         env['SERVER_NAME'] = self.server.server_name
  157.         env['GATEWAY_INTERFACE'] = 'CGI/1.1'
  158.         env['SERVER_PROTOCOL'] = self.protocol_version
  159.         env['SERVER_PORT'] = str(self.server.server_port)
  160.         env['REQUEST_METHOD'] = self.command
  161.         uqrest = urllib.unquote(rest)
  162.         env['PATH_INFO'] = uqrest
  163.         env['PATH_TRANSLATED'] = self.translate_path(uqrest)
  164.         env['SCRIPT_NAME'] = scriptname
  165.         if query:
  166.             env['QUERY_STRING'] = query
  167.         
  168.         host = self.address_string()
  169.         if host != self.client_address[0]:
  170.             env['REMOTE_HOST'] = host
  171.         
  172.         env['REMOTE_ADDR'] = self.client_address[0]
  173.         authorization = self.headers.getheader('authorization')
  174.         if authorization:
  175.             authorization = authorization.split()
  176.             if len(authorization) == 2:
  177.                 import base64 as base64
  178.                 import binascii as binascii
  179.                 env['AUTH_TYPE'] = authorization[0]
  180.                 if authorization[0].lower() == 'basic':
  181.                     
  182.                     try:
  183.                         authorization = base64.decodestring(authorization[1])
  184.                     except binascii.Error:
  185.                         pass
  186.  
  187.                     authorization = authorization.split(':')
  188.                     if len(authorization) == 2:
  189.                         env['REMOTE_USER'] = authorization[0]
  190.                     
  191.                 
  192.             
  193.         
  194.         if self.headers.typeheader is None:
  195.             env['CONTENT_TYPE'] = self.headers.type
  196.         else:
  197.             env['CONTENT_TYPE'] = self.headers.typeheader
  198.         length = self.headers.getheader('content-length')
  199.         if length:
  200.             env['CONTENT_LENGTH'] = length
  201.         
  202.         accept = []
  203.         for line in self.headers.getallmatchingheaders('accept'):
  204.             if line[:1] in '\t\n\r ':
  205.                 accept.append(line.strip())
  206.                 continue
  207.             accept = accept + line[7:].split(',')
  208.         
  209.         env['HTTP_ACCEPT'] = ','.join(accept)
  210.         ua = self.headers.getheader('user-agent')
  211.         if ua:
  212.             env['HTTP_USER_AGENT'] = ua
  213.         
  214.         co = filter(None, self.headers.getheaders('cookie'))
  215.         if co:
  216.             env['HTTP_COOKIE'] = ', '.join(co)
  217.         
  218.         for k in ('QUERY_STRING', 'REMOTE_HOST', 'CONTENT_LENGTH', 'HTTP_USER_AGENT', 'HTTP_COOKIE'):
  219.             env.setdefault(k, '')
  220.         
  221.         os.environ.update(env)
  222.         self.send_response(200, 'Script output follows')
  223.         decoded_query = query.replace('+', ' ')
  224.         if self.have_fork:
  225.             args = [
  226.                 script]
  227.             if '=' not in decoded_query:
  228.                 args.append(decoded_query)
  229.             
  230.             nobody = nobody_uid()
  231.             self.wfile.flush()
  232.             pid = os.fork()
  233.             if pid != 0:
  234.                 (pid, sts) = os.waitpid(pid, 0)
  235.                 while select.select([
  236.                     self.rfile], [], [], 0)[0]:
  237.                     if not self.rfile.read(1):
  238.                         break
  239.                         continue
  240.                 if sts:
  241.                     self.log_error('CGI script exit status %#x', sts)
  242.                 
  243.                 return None
  244.             
  245.             
  246.             try:
  247.                 
  248.                 try:
  249.                     os.setuid(nobody)
  250.                 except os.error:
  251.                     pass
  252.  
  253.                 os.dup2(self.rfile.fileno(), 0)
  254.                 os.dup2(self.wfile.fileno(), 1)
  255.                 os.execve(scriptfile, args, os.environ)
  256.             self.server.handle_error(self.request, self.client_address)
  257.             os._exit(127)
  258.  
  259.         elif self.have_popen2 or self.have_popen3:
  260.             import shutil as shutil
  261.             if self.have_popen3:
  262.                 popenx = os.popen3
  263.             else:
  264.                 popenx = os.popen2
  265.             cmdline = scriptfile
  266.             if self.is_python(scriptfile):
  267.                 interp = sys.executable
  268.                 if interp.lower().endswith('w.exe'):
  269.                     interp = interp[:-5] + interp[-4:]
  270.                 
  271.                 cmdline = '%s -u %s' % (interp, cmdline)
  272.             
  273.             if '=' not in query and '"' not in query:
  274.                 cmdline = '%s "%s"' % (cmdline, query)
  275.             
  276.             self.log_message('command: %s', cmdline)
  277.             
  278.             try:
  279.                 nbytes = int(length)
  280.             except (TypeError, ValueError):
  281.                 nbytes = 0
  282.  
  283.             files = popenx(cmdline, 'b')
  284.             fi = files[0]
  285.             fo = files[1]
  286.             if self.have_popen3:
  287.                 fe = files[2]
  288.             
  289.             if self.command.lower() == 'post' and nbytes > 0:
  290.                 data = self.rfile.read(nbytes)
  291.                 fi.write(data)
  292.             
  293.             while select.select([
  294.                 self.rfile._sock], [], [], 0)[0]:
  295.                 if not self.rfile._sock.recv(1):
  296.                     break
  297.                     continue
  298.             fi.close()
  299.             shutil.copyfileobj(fo, self.wfile)
  300.             if self.have_popen3:
  301.                 errors = fe.read()
  302.                 fe.close()
  303.                 if errors:
  304.                     self.log_error('%s', errors)
  305.                 
  306.             
  307.             sts = fo.close()
  308.             if sts:
  309.                 self.log_error('CGI script exit status %#x', sts)
  310.             else:
  311.                 self.log_message('CGI script exited OK')
  312.         else:
  313.             save_argv = sys.argv
  314.             save_stdin = sys.stdin
  315.             save_stdout = sys.stdout
  316.             save_stderr = sys.stderr
  317.             
  318.             try:
  319.                 save_cwd = os.getcwd()
  320.                 
  321.                 try:
  322.                     sys.argv = [
  323.                         scriptfile]
  324.                     if '=' not in decoded_query:
  325.                         sys.argv.append(decoded_query)
  326.                     
  327.                     sys.stdout = self.wfile
  328.                     sys.stdin = self.rfile
  329.                     execfile(scriptfile, {
  330.                         '__name__': '__main__' })
  331.                 finally:
  332.                     sys.argv = save_argv
  333.                     sys.stdin = save_stdin
  334.                     sys.stdout = save_stdout
  335.                     sys.stderr = save_stderr
  336.                     os.chdir(save_cwd)
  337.  
  338.             except SystemExit:
  339.                 sts = None
  340.                 self.log_error('CGI script exit status %s', str(sts))
  341.  
  342.             self.log_message('CGI script exited OK')
  343.  
  344.  
  345. nobody = None
  346.  
  347. def nobody_uid():
  348.     """Internal routine to get nobody's uid"""
  349.     global nobody
  350.     if nobody:
  351.         return nobody
  352.     
  353.     
  354.     try:
  355.         import pwd as pwd
  356.     except ImportError:
  357.         return -1
  358.  
  359.     
  360.     try:
  361.         nobody = pwd.getpwnam('nobody')[2]
  362.     except KeyError:
  363.         nobody = 1 + max(map((lambda x: x[2]), pwd.getpwall()))
  364.  
  365.     return nobody
  366.  
  367.  
  368. def executable(path):
  369.     '''Test for executable file.'''
  370.     
  371.     try:
  372.         st = os.stat(path)
  373.     except os.error:
  374.         return False
  375.  
  376.     return st.st_mode & 73 != 0
  377.  
  378.  
  379. def test(HandlerClass = CGIHTTPRequestHandler, ServerClass = BaseHTTPServer.HTTPServer):
  380.     SimpleHTTPServer.test(HandlerClass, ServerClass)
  381.  
  382. if __name__ == '__main__':
  383.     test()
  384.  
  385.